package com.ruoyi.web.controller.robot;

import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.poi.ExcelUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.vo.*;
import com.ruoyi.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/robot/statics")
@Slf4j
public class RobotStaticsController extends BaseController {

    @Resource
    private IOtherAbsenceRecordService IOtherAbsenceRecordService;
    @Resource
    private IOtherGiftReceptionRecordService IOtherGiftReceptionRecordService;
    @Resource
    private IOtherHostRecordService IOtherHostRecordService;
    @Resource
    private IOtherManualAbsenceRecordService IOtherManualAbsenceRecordService;
    @Resource
    private IOtherManualHostRecordService IOtherManualHostRecordService;
    @Resource
    private IOtherManualMicOrderRecordService IOtherManualMicOrderRecordService;
    @Resource
    private IOtherMicSlotClaimService IOtherMicSlotClaimService;
    @Resource
    private IOtherRobotInfoService otherRobotInfoService;
    @Resource
    private IOtherRoundConfigService otherRoundConfigService;

    @Resource
    private RobotRoomJobConfigController robotRoomJobConfigController;

    @Resource
    private RestTemplate restTemplate;

    /**
     * 麦序统计
     *
     * @param queryReq
     * @return
     */
    @GetMapping("/Micro")
    public AjaxResult MicroList(StaticsReq queryReq) {
        return success(getStaticsMicro(queryReq));
    }

    /**
     * 摸鱼统计
     *
     * @param queryReq
     * @return
     */
    @GetMapping("/SlackOff")
    public AjaxResult SlackOffList(StaticsReq queryReq) {
        return success(getSlackOffData(queryReq));
    }

    @GetMapping("/getRoomMember")
    public AjaxResult getRoomMemberList(StaticsReq queryReq) {
        return success(robotRoomJobConfigController.getRoomMember(queryReq.getRoomId()));
    }

    /**
     * 统计用户详情
     *
     * @param queryReq
     * @return
     */
    @GetMapping("/MemberInfo")
    public AjaxResult getStaticsMemberInfo(StaticsReq queryReq) {
        return success(getStaticsMember(queryReq));
    }


    /**
     * 统计用户信息
     *
     * @param queryReq
     * @return
     */
    public List<StaticsMemberRspVo> getStaticsMember(StaticsReq queryReq) {
        List<StaticsMemberRspVo> rsp = new ArrayList<>();

        if (queryReq.getMemberType().equals(StaticsMemberType.MICRO.getCode())) {
            List<OtherMicSlotClaim> otherMicSlotClaimByMember = IOtherMicSlotClaimService.getOtherMicSlotClaimByMember(queryReq.getRoomId(), queryReq.getWxid(), queryReq.getStartDate(), queryReq.getEndDate(), queryReq.getStartTime(), queryReq.getEndTime());
            Map<LocalDate, List<String>> micSlotMap = new HashMap<>();
            for (OtherMicSlotClaim otherMicSlotClaim : otherMicSlotClaimByMember) {
                List<String> schedules = micSlotMap.get(otherMicSlotClaim.getRoundStartTime().toLocalDate());
                if (schedules == null) {
                    schedules = new ArrayList<>();
                    schedules.add(changeScheduleOne(otherMicSlotClaim.getRoundStartTime()));
                    micSlotMap.put(otherMicSlotClaim.getRoundStartTime().toLocalDate(), schedules);
                } else {
                    schedules.add(changeScheduleOne(otherMicSlotClaim.getRoundStartTime()));
                }
            }
            micSlotMap.forEach((localDate, strings) -> {
                StaticsMemberRspVo staticsMemberRspVo = new StaticsMemberRspVo();
                staticsMemberRspVo.setDate(localDate);
                staticsMemberRspVo.setSchedule(strings);
                rsp.add(staticsMemberRspVo);
            });
        } else if (queryReq.getMemberType().equals(StaticsMemberType.BLACK.getCode())) {
            List<OtherAbsenceRecord> otherMicSlotClaimByMember = IOtherAbsenceRecordService.getAbsenceRecordByMember(queryReq.getRoomId(), queryReq.getWxid(), queryReq.getStartDate(), queryReq.getEndDate(), queryReq.getStartTime(), queryReq.getEndTime());
            Map<LocalDate, List<String>> micSlotMap = new HashMap<>();
            for (OtherAbsenceRecord otherMicSlotClaim : otherMicSlotClaimByMember) {
                List<String> schedules = micSlotMap.get(otherMicSlotClaim.getRoundStartTime().toLocalDate());
                if (schedules == null) {
                    schedules = new ArrayList<>();
                    schedules.add(changeScheduleOne(otherMicSlotClaim.getRoundStartTime()));
                    micSlotMap.put(otherMicSlotClaim.getRoundStartTime().toLocalDate(), schedules);
                } else {
                    schedules.add(changeScheduleOne(otherMicSlotClaim.getRoundStartTime()));
                }
            }
            micSlotMap.forEach((localDate, strings) -> {
                StaticsMemberRspVo staticsMemberRspVo = new StaticsMemberRspVo();
                staticsMemberRspVo.setDate(localDate);
                staticsMemberRspVo.setSchedule(strings);
                rsp.add(staticsMemberRspVo);
            });
        } else if (queryReq.getMemberType().equals(StaticsMemberType.HOST.getCode())) {
            List<String> lastTimeReq = checkReqIsOutTime(queryReq);
            List<OtherHostRecord> otherMicSlotClaimByMember = IOtherHostRecordService.getHostRecordByMember(queryReq.getRoomId(), queryReq.getWxid(), queryReq.getStartDate(), lastTimeReq.get(0), queryReq.getStartTime(), lastTimeReq.get(1));
            Map<LocalDate, List<String>> micSlotMap = new HashMap<>();
            for (OtherHostRecord otherMicSlotClaim : otherMicSlotClaimByMember) {
                List<String> schedules = micSlotMap.get(otherMicSlotClaim.getRoundStartTime().toLocalDate());
                if (schedules == null) {
                    schedules = new ArrayList<>();
                    schedules.add(changeScheduleOne(otherMicSlotClaim.getRoundStartTime()));
                    micSlotMap.put(otherMicSlotClaim.getRoundStartTime().toLocalDate(), schedules);
                } else {
                    schedules.add(changeScheduleOne(otherMicSlotClaim.getRoundStartTime()));
                }
            }
            micSlotMap.forEach((localDate, strings) -> {
                StaticsMemberRspVo staticsMemberRspVo = new StaticsMemberRspVo();
                staticsMemberRspVo.setDate(localDate);
                staticsMemberRspVo.setSchedule(strings);
                rsp.add(staticsMemberRspVo);
            });
        } else {
            return new ArrayList<>();
        }

        return rsp.stream().sorted(Comparator.comparing(StaticsMemberRspVo::getDate)).toList();

    }


    private String changeScheduleOne(LocalDateTime roundStartTime) {
        int end = roundStartTime.getHour() + 1;
        return roundStartTime.getHour() + "~" + end;
    }

    private String changeSchedule(LocalDateTime roundStartTime, LocalDateTime roundEndTime) {
        if (roundStartTime.getHour() == 23 && roundEndTime.getHour() == 0) {
            return roundStartTime.getHour() + "~" + 24;
        }
        return roundStartTime.getHour() + "~" + roundEndTime.getHour();

    }

    /**
     * 获取自由报备项目
     *
     * @param roomID
     * @return
     */
    public List<String> getFreeReportItem(String roomID) {
        List<OtherRoundConfig> otherRoundConfigs = otherRoundConfigService.selectRoundConfigByRoomId(roomID);
        OtherRoundConfig otherRoundConfig = otherRoundConfigs.get(0);
        String[] split = otherRoundConfig.getClockInItems().split(",");
        return Arrays.stream(split).filter(s -> !s.equals("黑麦"))
                .filter(s -> !s.equals("麦序"))
                .filter(s -> !s.equals("任务过"))
                .filter(s -> !s.equals("任务未过"))
                .filter(s -> !s.equals("任务排"))
                .filter(s -> !s.equals("置顶卡"))
                .filter(s -> !s.equals("接走"))
                .toList();
    }


    /**
     * 摸鱼名单：普通麦序 + 主持麦序 =0
     *
     * @param queryReq
     * @return
     */
    public List<StaticsSlackOffDataRspVo> getSlackOffData(StaticsReq queryReq) {
        List<StaticsSlackOffDataRspVo> slackOffDataRspVos = new ArrayList<>();
        Map<String, Map<String, String>> roomMember = robotRoomJobConfigController.getRoomMember(queryReq.getRoomId());
        //获取麦序原始数据
        List<HashMap> micSlotClaimSourceMap = IOtherMicSlotClaimService.getMicSlotClaim(queryReq.getRoomId(), queryReq.getStartDate(), queryReq.getEndDate(), queryReq.getStartTime(), queryReq.getEndTime());
        Map<String, StaticsDataTemp> tempmicSlotClaimMap = new HashMap<>();
        micSlotClaimSourceMap.forEach(record -> {
            String wxid = (String) record.get("wxid");
            String displayName = "";
            if (roomMember.get(wxid) == null) {
                displayName = (String) record.get("displayName");
            } else {
                displayName = getUserDisplayName(roomMember, wxid);
            }


            Long count = (Long) record.get("operationcount");
            StaticsDataTemp temp = new StaticsDataTemp();
            temp.setWxid(wxid);
            temp.setDisplayName(displayName);
            temp.setSourcecount(count.doubleValue());
            tempmicSlotClaimMap.put(wxid, temp);
        });

        List<String> lastTimeReq = checkReqIsOutTime(queryReq);
        //获取主持原始数据
        List<HashMap> hostRecordSourceMap = IOtherHostRecordService.getHostRecord(queryReq.getRoomId(), queryReq.getStartDate(), lastTimeReq.get(0), queryReq.getStartTime(), lastTimeReq.get(1));
        Map<String, StaticsDataTemp> temphostRecordMap = new HashMap<>();
        hostRecordSourceMap.forEach(record -> {
            String wxid = (String) record.get("wxid");

            String displayName = "";
            if (roomMember.get(wxid) == null) {
                displayName = (String) record.get("displayName");
            } else {
                displayName = getUserDisplayName(roomMember, wxid);
            }
            Long count = (Long) record.get("operationcount");
            StaticsDataTemp temp = new StaticsDataTemp();
            temp.setWxid(wxid);
            temp.setDisplayName(displayName);
            temp.setSourcecount(count.doubleValue());
            temphostRecordMap.put(wxid, temp);
        });

        //获取机器人信息 摸鱼名单要过滤机器人
        List<OtherRobotInfo> robotInfoList = otherRobotInfoService.selectOtherRobotInfoList();
        List<String> robotIdList = new ArrayList<>();
        robotInfoList.forEach(record -> {
            robotIdList.add(record.getWxid());
        });

        //找到摸鱼摸鱼名单
        List<String> slackOffIds = new ArrayList<>();
        roomMember.forEach((wxid, temp) -> {
            //过滤机器人
            if (robotIdList.contains(wxid)) {
                return;
            }

            StaticsDataTemp staticsDataTemp = tempmicSlotClaimMap.get(wxid);
            StaticsDataTemp staticsDataTemp1 = temphostRecordMap.get(wxid);
            if (staticsDataTemp == null && staticsDataTemp1 == null) {
                slackOffIds.add(wxid);
            }
        });

        //找到用户最新的麦序时间
        Map<String, LocalDateTime> rspMap = new HashMap<>();
        QueryWrapper<OtherMicSlotClaim> queryWrapperCommonLast = new QueryWrapper<>();
        queryWrapperCommonLast.eq("roomID", queryReq.getRoomId());
        queryWrapperCommonLast.ge("onQueueIndex", 0);
        queryWrapperCommonLast.in("wxid", slackOffIds);
        queryWrapperCommonLast.groupBy("wxid");
        queryWrapperCommonLast.groupBy("roomID");
        if (!slackOffIds.isEmpty()) {
            List<Map<String, Object>> memberLastRecord = IOtherMicSlotClaimService.getMemberLastRecord(queryWrapperCommonLast);
            if (!memberLastRecord.isEmpty()) {
                memberLastRecord.forEach(record -> {

                    if (((String) record.get("roomID")).equals(queryReq.getRoomId())) {
                        rspMap.put((String) record.get("wxid"), (LocalDateTime) record.get("lasttime"));
                    }


                });
            }

        }

        //找到用户最新的主持时间
        QueryWrapper<OtherHostRecord> queryWrapperHostLast = new QueryWrapper<>();
        queryWrapperHostLast.in("wxid", slackOffIds);
        queryWrapperHostLast.eq("roomID", queryReq.getRoomId());
        queryWrapperHostLast.eq("deleteFlag", 0);
        queryWrapperHostLast.groupBy("roomID");
        queryWrapperHostLast.groupBy("wxid");
        if (!slackOffIds.isEmpty()) {
            List<Map<String, Object>> hostLastRecord = IOtherHostRecordService.getMemberLastRecord(queryWrapperHostLast);
            if (!hostLastRecord.isEmpty()) {
                hostLastRecord.forEach(record -> {
                    if (((String) record.get("roomID")).equals(queryReq.getRoomId())) {
                        if (rspMap.get((String) record.get("wxid")) != null && ((LocalDateTime) record.get("lasttime")).isBefore(rspMap.get((String) record.get("wxid")))) {
                        } else {
                            rspMap.put((String) record.get("wxid"), (LocalDateTime) record.get("lasttime"));
                        }
                    }
                });
            }
        }

        slackOffIds.stream().forEach(id -> {

            StaticsSlackOffDataRspVo slackOffDataRspVo = new StaticsSlackOffDataRspVo();
            slackOffDataRspVo.setWxid(id);
            slackOffDataRspVo.setLastTime(rspMap.get(id));
            slackOffDataRspVo.setDisplayName(getUserDisplayName(roomMember, id));
            slackOffDataRspVos.add(slackOffDataRspVo);
        });

        List<StaticsSlackOffDataRspVo> temp = slackOffDataRspVos;
        if (queryReq.getSortingField().equals("displayName")) {

            if (queryReq.getSortingOrder().equals("asc")) {
                temp = slackOffDataRspVos.stream().sorted(Comparator.comparing(StaticsSlackOffDataRspVo::getWxid)).toList();
            } else {
                temp = slackOffDataRspVos.stream().sorted(Comparator.comparing(StaticsSlackOffDataRspVo::getWxid).reversed()).toList();
            }

        } else {
            if (queryReq.getSortingOrder().equals("asc")) {
                temp = slackOffDataRspVos.stream().sorted(Comparator.comparing(StaticsSlackOffDataRspVo::getLastTime, Comparator.nullsLast(Comparator.naturalOrder()))).toList();
            } else {
                temp = slackOffDataRspVos.stream().sorted(Comparator.comparing(StaticsSlackOffDataRspVo::getLastTime, Comparator.nullsLast(Comparator.naturalOrder())).reversed()).toList();
            }
        }

        return temp;
    }


    private String getUserDisplayName(Map<String, Map<String, String>> roomMember, String wxid) {

        if (roomMember.get(wxid).get("chatroomDisplayName") != null && !roomMember.get(wxid).get("chatroomDisplayName").isEmpty()) {
            return roomMember.get(wxid).get("chatroomDisplayName");
        }

        if (roomMember.get(wxid).get("chatroomNickName") != null && !roomMember.get(wxid).get("chatroomNickName").isEmpty()) {
            return roomMember.get(wxid).get("chatroomNickName");
        }

        return roomMember.get(wxid).get("nickName");
    }


    private List<String> checkReqIsOutTime(StaticsReq queryReq) {
        String timeString = queryReq.getEndDate() + " " + queryReq.getEndTime();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime dateTime = LocalDateTime.parse(timeString, formatter);
        List<String> outTimeList = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        if (dateTime.isBefore(now)) {
            outTimeList.add(queryReq.getEndDate());
            outTimeList.add(queryReq.getEndTime());
        } else {

            outTimeList.add(now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            outTimeList.add(now.format(DateTimeFormatter.ofPattern("HH:mm:ss")));
        }

        return outTimeList;
    }


    @GetMapping("/export")
    public void exportStatisData(StaticsReq req, HttpServletResponse response) throws IOException {
        String filename = "";
        boolean oneDayFlag = false;
        if (req.getStartDate().equals(req.getEndDate())) {
            oneDayFlag = true;
            filename = req.getStartDate() + " " + req.getRoomName() + "数据" + ".xlsx";
        } else {
            filename = req.getStartDate() + "-" + req.getEndDate() + " " + req.getRoomName() + "数据" + ".xlsx";
        }

        ExcelWriter excelWriter = ExcelUtils.getWriter(response);

        String startDate = req.getStartDate();
        String endDate = req.getEndDate();

        //是否单天
        if (oneDayFlag) {
            ExcelUtils.writeSheet(excelWriter,
                    "统计",
                    createExcelHead(req),
                    getAllDataList(convertStaticsExportMergeList(req), req));
        } else {
            //多天处理
            ExcelUtils.writeSheet(excelWriter,
                    "统计",
                    createExcelHead(req),
                    getAllDataList(convertStaticsExportMergeList(req), req));

            //针对每天
            LocalDate nowdata = LocalDate.parse(req.getStartDate());
            while (nowdata.isBefore(LocalDate.parse(endDate)) || nowdata.isEqual(LocalDate.parse(endDate))) {

                req.setStartDate(nowdata.toString());
                req.setEndDate(nowdata.toString());

                ExcelUtils.writeSheet(excelWriter,
                        nowdata.toString(),
                        createExcelHead(req),
                        getAllDataList(convertStaticsExportMergeList(req), req));

                nowdata = nowdata.plusDays(1);
            }

        }

        ExcelUtils.addHeader(response, excelWriter, filename);
    }


    /**
     * 获取动态数据
     *
     * @return
     */
    private List<List<String>> getAllDataList(List<StaticsExportMerge> mergeList, StaticsReq req) {
        List<List<String>> dataList = new ArrayList<>();
        List<String> freeReportItem = getFreeReportItem(req.getRoomId());
        for (StaticsExportMerge staticsExportMerge : mergeList) {

            List<String> dataLine = new ArrayList<>();

            Class<? extends StaticsExportMerge> aClass = staticsExportMerge.getClass();
            Field[] declaredFields = aClass.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                boolean annotationPresent = declaredField.isAnnotationPresent(ExcelProperty.class);
                if (annotationPresent) {
                    try {
                        declaredField.setAccessible(true);
                        if (declaredField.get(staticsExportMerge) != null) {
                            dataLine.add(declaredField.get(staticsExportMerge).toString());
                        } else {
                            dataLine.add("");
                        }

                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }
                }
            }

            for (String itemname : freeReportItem) {
                Double aLong = staticsExportMerge.getFreeReport().get(itemname);
                if (aLong == null) {
                    dataLine.add("");
                } else {
                    dataLine.add(aLong.toString());
                }
            }

            dataList.add(dataLine);

        }

        return dataList;
    }

    /**
     * 合并数据
     *
     * @param req
     * @return
     */
    List<StaticsExportMerge> convertStaticsExportMergeList(StaticsReq req) {

        Map<String, StaticsExportMerge> map = new LinkedHashMap<>();
        List<StaticsExportMerge> mergeList = new ArrayList<>();

        //查找麦序
        List<StaticsMicroDataRspVo> staticsMicro = getStaticsMicro(req);


        Map<String, StaticsMicroDataRspVo> microMap = new LinkedHashMap<>();
        for (StaticsMicroDataRspVo staticsMicroDataRspVo : staticsMicro) {
            microMap.put(staticsMicroDataRspVo.getWxid(), staticsMicroDataRspVo);
        }

        microMap.forEach((k, v) -> {
            StaticsExportMerge staticsExportMerge = new StaticsExportMerge();
            staticsExportMerge.setWxid(v.getWxid());
            staticsExportMerge.setDisplayName(v.getDisplayName());
            staticsExportMerge.setHostCount(v.getHostCount());
            staticsExportMerge.setAbsenceCount(v.getAbsenceCount());
            staticsExportMerge.setMicSlotCount(v.getMicSlotCount());
            staticsExportMerge.setFreeReport(v.getFreeReport());

            map.put(k, staticsExportMerge);
        });


        //查找摸鱼名单
        List<StaticsSlackOffDataRspVo> slackOffData = getSlackOffData(req);
        Map<String, StaticsSlackOffDataRspVo> slackOffDataRspVoMap = new LinkedHashMap<>();
        for (StaticsSlackOffDataRspVo slackOffDatum : slackOffData) {
            slackOffDataRspVoMap.put(slackOffDatum.getWxid(), slackOffDatum);
        }

        slackOffDataRspVoMap.forEach((k, v) -> {

            StaticsExportMerge staticsExportMerge = map.get(k);
            if (staticsExportMerge == null) {
                staticsExportMerge = new StaticsExportMerge();
                staticsExportMerge.setWxid(v.getWxid());
                staticsExportMerge.setDisplayName(v.getDisplayName());
                staticsExportMerge.setLastTime(v.getLastTime());
                map.put(k, staticsExportMerge);
            } else {
                staticsExportMerge.setLastTime(v.getLastTime());
            }

        });

        map.forEach((k, v) -> {
            mergeList.add(v);
        });

        return mergeList;
    }


    /**
     * 创建动态表头
     *
     * @return
     */
    private List<List<String>> createExcelHead(StaticsReq req) {

        List<List<String>> list = new ArrayList<List<String>>();
        List<String> freeReportItem = getFreeReportItem(req.getRoomId());

        //第一行表头
        List<String> head1 = new ArrayList<>();
        head1.add("日期");
        head1.add(req.getStartDate() + "-" + req.getEndDate());
        head1.add(req.getStartDate() + "-" + req.getEndDate());
        head1.add("时段");
        head1.add(req.getStartTime() + "-" + req.getEndTime());
        head1.add(req.getStartTime() + "-" + req.getEndTime());

        //第二行表头
        List<String> head2 = new ArrayList<>();
        head2.add("成员");
        head2.add("麦序");
        head2.add("主持麦序");
        head2.add("黑麦");
        head2.add("最近麦序时间");

        //自由报备项目
        for (String s : freeReportItem) {
            head2.add(s);
        }


        //2行字段长度对齐
        if (head2.size() > head1.size()) {
            for (int i = 0; i < head2.size() - head1.size(); i++) {
                head1.add(" ");
            }
        }

        int size = head2.size() > head1.size() ? head2.size() : head1.size();
        //整合数据
        for (int i = 0; i < size; i++) {
            List<String> temp = new ArrayList<String>();
            if (head1.size() > i) {
                temp.add(head1.get(i));
            } else {
                temp.add("");
            }

            if (head2.size() > i) {
                temp.add(head2.get(i));
            } else {
                temp.add("");
            }

            list.add(temp);
        }


        return list;

    }


    /**
     * 截取出来
     *
     * @param giftName
     * @param messageText
     * @return
     */
    public Double getReportValue(String giftName, String messageText) {
        Double reportValue = 1d;
        StringBuilder report = new StringBuilder();
        //截取数字字符串
        for (int i = giftName.length(); i < messageText.length(); i++) {
            char c = messageText.charAt(i);
            if (checkChar(c)) {
                report.append(c);
            } else {
                break;
            }
        }


        if (report.isEmpty()) {
            return reportValue;
        }


        //去除最后不是数字的情况
        while (!report.isEmpty() && !Character.isDigit(report.charAt(report.length() - 1))) {
            report.deleteCharAt(report.length() - 1);
        }


        //获取值
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
        Object result;
        try {
            result = engine.eval(report.toString());
            if (result instanceof Double) {
                reportValue = (Double) result;
            }
            if (result instanceof Integer) {
                Integer temp = (Integer) result;
                reportValue = Double.valueOf(temp);
            }
        } catch (Exception e) {
        }

        return reportValue;
    }


    public static double evaluate(String expression) {
        expression = expression.replaceAll("\\s", ""); // 移除空格以提高简单性
        String[] parts = expression.split("(?<=[-+*/])"); // 分割操作符两侧的数字和操作符
        double result = 0;
        char operation = '+'; // 默认操作符为加号，用于初始化结果值计算
        for (String part : parts) {
            if (part.matches("[+\\-*/]")) { // 判断是否为操作符
                operation = part.charAt(0);
            } else { // 否则为数字部分，进行计算并更新结果和操作符
                double value = Double.parseDouble(part);
                switch (operation) {
                    case '+':
                        result += value;
                        break;
                    case '-':
                        result -= value;
                        break;
                    case '*':
                        result *= value;
                        break;
                    case '/':
                        result /= value;
                        break; // 注意：这里不考虑除以0的情况，实际应用中需要处理这种情况
                }
                operation = '+'; // 重置操作符为加号，为下一个操作准备
            }
        }
        return result; // 返回最终结果
    }

    private boolean checkChar(char c) {

        if (Character.isDigit(c)) {
            return true;
        }

        if (c == '+' || c == '-' || c == '*') {
            return true;
        }

        if (c == '.') {
            return true;
        }

        return false;

    }


    /**
     * 普通麦序
     *
     * @param queryReq
     * @return
     */
    public List<StaticsMicroDataRspVo> getStaticsMicro(StaticsReq queryReq) {
        List<StaticsMicroDataRspVo> staticsMicroDataRspVos = new ArrayList<>();
        log.info("getStaticsMicro " + queryReq.toString());
        //获取群成员
        Map<String, Map<String, String>> roomMember = robotRoomJobConfigController.getRoomMember(queryReq.getRoomId());

        Map<String, String> wiIdInfo = new HashMap<>();
        //获取麦序原始数据
        List<HashMap> micSlotClaimSourceMap = IOtherMicSlotClaimService.getMicSlotClaim(queryReq.getRoomId(), queryReq.getStartDate(), queryReq.getEndDate(), queryReq.getStartTime(), queryReq.getEndTime());
        Map<String, StaticsDataTemp> tempmicSlotClaimMap = new HashMap<>();
        micSlotClaimSourceMap.forEach(record -> {
            String wxid = (String) record.get("wxid");
            String displayName = "";
            if (roomMember.get(wxid) == null) {
                displayName = (String) record.get("displayName");
            } else {
                displayName = getUserDisplayName(roomMember, wxid);
            }

            Long count = (Long) record.get("operationcount");
            wiIdInfo.put(wxid, displayName);
            StaticsDataTemp temp = new StaticsDataTemp();
            temp.setWxid(wxid);
            temp.setDisplayName(displayName);
            temp.setSourcecount(count.doubleValue());
            if (tempmicSlotClaimMap.get(wxid) != null) {
                StaticsDataTemp staticsDataTemp = tempmicSlotClaimMap.get(wxid);
                temp.setSourcecount(count.doubleValue() + staticsDataTemp.getSourcecount());
            }
            tempmicSlotClaimMap.put(wxid, temp);

        });


        //获取黑麦原始数据
        List<HashMap> absenceRecordSourceMap = IOtherAbsenceRecordService.getAbsenceRecord(queryReq.getRoomId(), queryReq.getStartDate(), queryReq.getEndDate(), queryReq.getStartTime(), queryReq.getEndTime());
        Map<String, StaticsDataTemp> tempabsenceRecordMap = new HashMap<>();
        absenceRecordSourceMap.forEach(record -> {
            String wxid = (String) record.get("wxid");
            String displayName = "";
            if (roomMember.get(wxid) == null) {
                displayName = (String) record.get("displayName");
            } else {
                displayName = getUserDisplayName(roomMember, wxid);
            }
            Long count = (Long) record.get("operationcount");
            wiIdInfo.put(wxid, displayName);
            StaticsDataTemp temp = new StaticsDataTemp();
            temp.setWxid(wxid);
            temp.setDisplayName(displayName);
            temp.setSourcecount(count.doubleValue());
            if (tempabsenceRecordMap.get(wxid) != null) {
                StaticsDataTemp staticsDataTemp = tempabsenceRecordMap.get(wxid);
                temp.setSourcecount(count.doubleValue() + staticsDataTemp.getSourcecount());
            }
            tempabsenceRecordMap.put(wxid, temp);
        });


        List<String> lastTimeReq = checkReqIsOutTime(queryReq);

        //获取主持原始数据
        List<HashMap> hostRecordSourceMap = IOtherHostRecordService.getHostRecord(queryReq.getRoomId(), queryReq.getStartDate(), lastTimeReq.get(0), queryReq.getStartTime(), lastTimeReq.get(1));
        Map<String, StaticsDataTemp> temphostRecordMap = new HashMap<>();
        hostRecordSourceMap.forEach(record -> {
            String wxid = (String) record.get("wxid");
            String displayName = "";
            if (roomMember.get(wxid) == null) {
                displayName = (String) record.get("displayName");
            } else {
                displayName = getUserDisplayName(roomMember, wxid);
            }
            //String displayName = (String) record.get("displayName");
//            String displayName = roomMember.get(wxid).get("nickName");
            Long count = (Long) record.get("operationcount");
            wiIdInfo.put(wxid, displayName);
            StaticsDataTemp temp = new StaticsDataTemp();
            temp.setWxid(wxid);
            temp.setDisplayName(displayName);
            temp.setSourcecount(count.doubleValue());
            if (temphostRecordMap.get(wxid) != null) {
                StaticsDataTemp staticsDataTemp = temphostRecordMap.get(wxid);
                temp.setSourcecount(count.doubleValue() + staticsDataTemp.getSourcecount());
            }
            temphostRecordMap.put(wxid, temp);
        });

        //获取麦序更新数据
        List<HashMap> manualMicOrderRecord = IOtherManualMicOrderRecordService.getManualMicOrderRecord(queryReq.getRoomId(), queryReq.getStartDate(), queryReq.getEndDate(), queryReq.getStartTime(), queryReq.getEndTime());
        Map<String, StaticsDataTemp> tempmanualMicOrderMap = new HashMap<>();
        manualMicOrderRecord.forEach(record -> {
            String wxid = (String) record.get("wxid");
            String displayName = "";
            if (roomMember.get(wxid) == null) {
                displayName = (String) record.get("displayName");
            } else {
                displayName = getUserDisplayName(roomMember, wxid);
            }
            BigDecimal count = (BigDecimal) record.get("totalvalue");
            wiIdInfo.put(wxid, displayName);
            StaticsDataTemp temp = new StaticsDataTemp();
            temp.setWxid(wxid);
            temp.setDisplayName(displayName);
            temp.setSourcecount(count.doubleValue());
            if (tempmanualMicOrderMap.get(wxid) != null) {
                StaticsDataTemp staticsDataTemp = tempmanualMicOrderMap.get(wxid);
                temp.setSourcecount(count.doubleValue() + staticsDataTemp.getSourcecount());
            }
            tempmanualMicOrderMap.put(wxid, temp);
        });

        //获取黑麦更新数据
        List<HashMap> manualAbsenceRecord = IOtherManualAbsenceRecordService.getManualAbsenceRecord(queryReq.getRoomId(), queryReq.getStartDate(), queryReq.getEndDate(), queryReq.getStartTime(), queryReq.getEndTime());
        Map<String, StaticsDataTemp> tempmanualAbsenceMap = new HashMap<>();
        manualAbsenceRecord.forEach(record -> {
            String wxid = (String) record.get("wxid");
            String displayName = "";
            if (roomMember.get(wxid) == null) {
                displayName = (String) record.get("displayName");
            } else {
                displayName = getUserDisplayName(roomMember, wxid);
            }
            BigDecimal count = (BigDecimal) record.get("totalvalue");
            wiIdInfo.put(wxid, displayName);
            StaticsDataTemp temp = new StaticsDataTemp();
            temp.setWxid(wxid);
            temp.setDisplayName(displayName);
            temp.setSourcecount(count.doubleValue());
            if (tempmanualAbsenceMap.get(wxid) != null) {
                StaticsDataTemp staticsDataTemp = tempmanualAbsenceMap.get(wxid);
                temp.setSourcecount(count.doubleValue() + staticsDataTemp.getSourcecount());
            }
            tempmanualAbsenceMap.put(wxid, temp);
        });


        //获取主持更新数据
        List<HashMap> manualHostRecord = IOtherManualHostRecordService.getManualHostRecord(queryReq.getRoomId(), queryReq.getStartDate(), queryReq.getEndDate(), queryReq.getStartTime(), queryReq.getEndTime());
        Map<String, StaticsDataTemp> tempmanualHostMap = new HashMap<>();
        manualHostRecord.forEach(record -> {
            String wxid = (String) record.get("wxid");
            String displayName = "";

            if (roomMember.get(wxid) == null) {
                displayName = (String) record.get("displayName");
            } else {
                displayName = getUserDisplayName(roomMember, wxid);
            }

            BigDecimal count = (BigDecimal) record.get("totalvalue");
            wiIdInfo.put(wxid, displayName);
            StaticsDataTemp temp = new StaticsDataTemp();
            temp.setWxid(wxid);
            temp.setDisplayName(displayName);
            temp.setSourcecount(count.doubleValue());
            if (tempmanualHostMap.get(wxid) != null) {
                StaticsDataTemp staticsDataTemp = tempmanualHostMap.get(wxid);
                temp.setSourcecount(count.doubleValue() + staticsDataTemp.getSourcecount());
            }
            tempmanualHostMap.put(wxid, temp);
        });

        //获取自由报备情况
        List<OtherGiftReceptionRecord> giftReceptionRecordSourceMap = IOtherGiftReceptionRecordService.getGiftReceptionRecord(queryReq.getRoomId(), queryReq.getStartDate(), queryReq.getEndDate(), queryReq.getStartTime(), queryReq.getEndTime());
        giftReceptionRecordSourceMap.forEach(record -> {
            record.setReportValue(getReportValue(record.getGiftName(), record.getTrimmedMessageText()));
        });

        Map<String, List<StaticsDataTemp>> tempgiftReceptionRecordMap = new HashMap<>();
        giftReceptionRecordSourceMap.forEach(record -> {
            String wxid = record.getWxid();
            String displayName = "";
            if (roomMember.get(wxid) == null) {
                displayName = record.getDisplayName();
            } else {
                displayName = getUserDisplayName(roomMember, wxid);
            }

            String giftName = record.getGiftName();
            Double count = record.getReportValue();
            wiIdInfo.put(wxid, displayName);
            StaticsDataTemp temp = new StaticsDataTemp();
            temp.setWxid(wxid);
            temp.setDisplayName(displayName);
            temp.setGiftName(giftName);
            temp.setSourcecount(count);
            List<StaticsDataTemp> staticsDataTemps = tempgiftReceptionRecordMap.get(wxid);
            if (staticsDataTemps == null) {
                staticsDataTemps = new ArrayList<>();
                staticsDataTemps.add(temp);
                tempgiftReceptionRecordMap.put(wxid, staticsDataTemps);
            } else {
                staticsDataTemps.add(temp);
            }

        });

        wiIdInfo.forEach((wxid, displayName) -> {

            StaticsMicroDataRspVo staticsMicroDataRspVo = new StaticsMicroDataRspVo();
            staticsMicroDataRspVo.setWxid(wxid);
            staticsMicroDataRspVo.setDisplayName(displayName);

            //获取麦序原始数据
            StaticsDataTemp staticsDataTemp = tempmicSlotClaimMap.get(wxid);
            if (staticsDataTemp != null) {
                staticsMicroDataRspVo.setMicSlotCount((long) Math.floor(staticsDataTemp.getSourcecount()));
            }

            //获取黑麦原始数据
            StaticsDataTemp absenceRecord = tempabsenceRecordMap.get(wxid);
            if (absenceRecord != null) {
                staticsMicroDataRspVo.setAbsenceCount((long) Math.floor(absenceRecord.getSourcecount()));
            }

            //获取主持原始数据
            StaticsDataTemp temphostRecord = temphostRecordMap.get(wxid);
            if (temphostRecord != null) {
                staticsMicroDataRspVo.setHostCount((long) Math.floor(temphostRecord.getSourcecount()));
            }

            //获取自由报备情况
            List<StaticsDataTemp> tempReceptionRecord = tempgiftReceptionRecordMap.get(wxid);
            if (tempReceptionRecord != null) {
                tempReceptionRecord.forEach(record -> {
                    if (staticsMicroDataRspVo.getFreeReport().get(record.getGiftName()) == null) {
                        staticsMicroDataRspVo.getFreeReport().put(record.getGiftName(), record.getSourcecount());
                    } else {
                        staticsMicroDataRspVo.getFreeReport().put(record.getGiftName(), staticsMicroDataRspVo.getFreeReport().get(record.getGiftName()) + record.getSourcecount());
                    }


                });
            }

            //获取麦序更新数据
            StaticsDataTemp manualMicOrder = tempmanualMicOrderMap.get(wxid);
            if (manualMicOrder != null) {
                staticsMicroDataRspVo.setMicSlotCount((long) Math.floor(staticsMicroDataRspVo.getMicSlotCount() + manualMicOrder.getSourcecount()));
            }

            StaticsDataTemp manualAbsence = tempmanualAbsenceMap.get(wxid);
            if (manualAbsence != null) {
                staticsMicroDataRspVo.setAbsenceCount((long) Math.floor(staticsMicroDataRspVo.getAbsenceCount() + manualAbsence.getSourcecount()));
            }


            StaticsDataTemp manualHost = tempmanualHostMap.get(wxid);
            if (manualHost != null) {
                staticsMicroDataRspVo.setHostCount((long) Math.floor(staticsMicroDataRspVo.getHostCount() + manualHost.getSourcecount()));
            }

            staticsMicroDataRspVos.add(staticsMicroDataRspVo);
        });


        //排序
        List<StaticsMicroDataRspVo> temp = new ArrayList<>();
        switch (queryReq.getSortingField()) {
            case "hostCount":
                if (queryReq.getSortingOrder().equals("asc")) {
                    temp = staticsMicroDataRspVos.stream().sorted(Comparator.comparing(StaticsMicroDataRspVo::getHostCount)).toList();
                } else {
                    temp = staticsMicroDataRspVos.stream().sorted(Comparator.comparing(StaticsMicroDataRspVo::getHostCount).reversed()).toList();
                }
                break;

            case "absenceCount":
                if (queryReq.getSortingOrder().equals("asc")) {
                    temp = staticsMicroDataRspVos.stream().sorted(Comparator.comparing(StaticsMicroDataRspVo::getAbsenceCount)).toList();
                } else {
                    temp = staticsMicroDataRspVos.stream().sorted(Comparator.comparing(StaticsMicroDataRspVo::getAbsenceCount).reversed()).toList();
                }
                break;


            case "displayName":
                if (queryReq.getSortingOrder().equals("asc")) {
                    temp = staticsMicroDataRspVos.stream().sorted(Comparator.comparing(StaticsMicroDataRspVo::getDisplayName)).toList();
                } else {
                    temp = staticsMicroDataRspVos.stream().sorted(Comparator.comparing(StaticsMicroDataRspVo::getDisplayName).reversed()).toList();
                }
                break;

            case "freeReport":
                if (queryReq.getSortingOrder().equals("asc")) {
                    temp = staticsMicroDataRspVos.stream().sorted(Comparator.comparing((StaticsMicroDataRspVo app) -> app.getFreeReport().get(queryReq.getRemark()) == null ? 0 : app.getFreeReport().get(queryReq.getRemark()))).toList();
                } else {
                    temp = staticsMicroDataRspVos.stream().sorted(Comparator.comparing((StaticsMicroDataRspVo app) -> app.getFreeReport().get(queryReq.getRemark()) == null ? 0 : app.getFreeReport().get(queryReq.getRemark())).reversed()).toList();
                }
                break;

            default:
                if (queryReq.getSortingOrder().equals("asc")) {
                    temp = staticsMicroDataRspVos.stream().sorted(Comparator.comparing(StaticsMicroDataRspVo::getMicSlotCount)).toList();
                } else {
                    temp = staticsMicroDataRspVos.stream().sorted(Comparator.comparing(StaticsMicroDataRspVo::getMicSlotCount).reversed()).toList();
                }
                break;
        }

        return temp;
    }
}
